package com.yypx.common.utils;

import java.io.File;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.InputSource;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

/**
 * XML操作工具类
 * 
 * @author linweiming
 * 
 */
public class XMLUtil {
	public static String XML_HEAD = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";

	public static String changeEscapeChar(String str) {
		if (StringUtil.isStringHasContent(str)) {
			return str.replace("&", "&amp;").replace("'", "&apos;").replace("\"", "&quot;").replace("<", "&lt;").replace(">", "&gt;");
		} else
			return str;
	}

	private static final Log LOG = LogFactory.getLog(XMLUtil.class);

	/**
	 * 读取XML文件,返回Document对象
	 * 
	 * @param file
	 * @return
	 */
	public static Document getDocument(File file) {
		Document document = null;
		try {
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			document = builder.parse(file);
		} catch (Exception e) {
			LOG.error(e);
		}
		return document;
	}

	/**
	 * 读取XSL文件,返回Document对象
	 * 
	 * @param file
	 * @return
	 */
	public static Document getXSLDocument(File file) {
		Document document = null;
		try {
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			factory.setNamespaceAware(true);
			DocumentBuilder builder = factory.newDocumentBuilder();
			document = builder.parse(file);
		} catch (Exception e) {
			LOG.error(e);
		}
		return document;
	}

	/**
	 * 读取XML String,返回Document对象
	 * 
	 * @param file
	 * @return
	 */
	public static Document getDocument(String xmlString) {
		Document document = null;
		try {
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			StringReader sr = new StringReader(xmlString);
			InputSource is = new InputSource(sr);
			document = builder.parse(is);
		} catch (Exception e) {
			LOG.error(e);
		}
		return document;
	}

	/**
	 * 获取某元素element下的子元素nodeName的值
	 * 
	 * @param element
	 * @param nodeName
	 * @return
	 */
	public static String getNodeValue(Element element, String nodeName) {
		try {
			return ((Text) element.getElementsByTagName(nodeName).item(0).getFirstChild()).getNodeValue();
		} catch (Exception e) {
			LOG.error(e);
			return null;
		}
	}

	/**
	 * 将Map转换为XML
	 * 
	 * @param map
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static String simpleMap2Xml(Map map, String rootname) {
		StringBuilder sBuilder = new StringBuilder();
		Set<String> key = map.keySet();
		sBuilder.append("<".concat(rootname).concat(">"));
		for (Iterator it = key.iterator(); it.hasNext();) {
			String s = (String) it.next();
			if (map.get(s) != null) {
				sBuilder.append("<".concat(s).concat(">"));
				sBuilder.append(transChar(map.get(s).toString()));
				sBuilder.append("</".concat(s).concat(">"));
			}
		}
		sBuilder.append("</".concat(rootname).concat(">"));
		return sBuilder.toString();
	}

	/**
	 * 将XML转换为Map
	 * 
	 * @param xmlString
	 * @return
	 */
	public static Map<String, Object> simpleXml2Map(String xmlString) {
		Map<String, Object> map = new HashMap<String, Object>();
		Document document = XMLUtil.getDocument(xmlString);
		NodeList nodeList = document.getDocumentElement().getChildNodes();
		for (int i = 0; i < nodeList.getLength(); i++) {
			Element element = (Element) nodeList.item(i);
			map.put(element.getTagName(), reTransChar(element.getTextContent()));
		}
		return map;
	}

	/**
	 * 将XML转换为Map的List
	 * 
	 * @param xmlString
	 * @return
	 */
	public static List<Map<String, Object>> simpleXml2MapList(String xmlString) {
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		Document document = XMLUtil.getDocument(xmlString);
		NodeList nodeList = document.getDocumentElement().getChildNodes();
		for (int i = 0; i < nodeList.getLength(); i++) {
			NodeList nodeList2 = nodeList.item(i).getChildNodes();
			Map<String, Object> map = new HashMap<String, Object>();
			for (int j = 0; j < nodeList2.getLength(); j++) {
				Element element = (Element) nodeList2.item(j);
				map.put(element.getTagName(), reTransChar(element.getTextContent()));
			}
			list.add(map);
		}
		return list;
	}

	/**
	 * 将对象转成xml串
	 * 
	 * @param obj
	 * @param map
	 *            存放对象名所对应的xml元素名
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static String simpleObject2Xml(Object obj, Map map) {
		XStream xStream = new XStream(new DomDriver());
		if (map != null) {
			Iterator iter = map.keySet().iterator();
			while (iter.hasNext()) {
				Object elementName = iter.next();
				Object objectClass = map.get(elementName);
				xStream.alias(String.valueOf(elementName), (Class) objectClass);
			}
		}
		String xml = xStream.toXML(obj);
		return xml;
	}

	/**
	 * 将xml串转成对象
	 * 
	 * @param xml
	 * @param map
	 *            存放对象名所对应的xml元素名
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static Object simpleXml2Object(String xml, Map map) {
		XStream xStream = new XStream(new DomDriver());
		if (map != null) {
			Iterator iter = map.keySet().iterator();
			while (iter.hasNext()) {
				Object elementName = iter.next();
				Object objectClass = map.get(elementName);
				xStream.alias(String.valueOf(elementName), (Class) objectClass);
			}
		}
		Object reobj = xStream.fromXML(xml);
		return reobj;
	}

	/**
	 * xml特殊字符转义
	 * 
	 * @param xml
	 */
	public static String transChar(String xml) {
		return xml.replace("<", "&lt;").replace(">", "&gt;").replace("&", "&amp;").replace("'", "&apos;").replace("\"", "&quot;");
	}

	/**
	 * xml特殊字符反转义
	 * 
	 * @param xml
	 * @return
	 */
	public static String reTransChar(String xml) {
		return xml.replace("&lt;", "<").replace("&gt;", ">").replace("&amp;", "&").replace("&apos;", "'").replace("&quot;", "\"");
	}
}
